Date: Fri Dec 13 12:54:45 2019
Scientist: Ran Yin
Sequencing (Waksman): Dibyendu Kumar
Statistics: Davit Sargsyan
Principal Investigator: Ah-Ng Kong

# Taxonomic Ranks:
# **K**ing **P**hillip **C**an n**O**t **F**ind **G**reen **S**ocks
# * Kingdom                
# * Phylum                    
# * Class                   
# * Order                   
# * Family     
# * Genus     
# * Species  
# options(stringsAsFactors = FALSE,
#         scipen = 999)
# # Increase mmemory size to 64 Gb----
# invisible(utils::memory.limit(65536))
# str(knitr::opts_chunk$get())
# # NOTE: the below does not work!
# knitr::opts_chunk$set(echo = FALSE, 
#                       message = FALSE,
#                       warning = FALSE,
#                       error = FALSE)
# require(knitr)
# require(kableExtra)
require(phyloseq)
Loading required package: phyloseq
# require(shiny)
require(data.table)
Loading required package: data.table
data.table 1.12.2 using 18 threads (see ?getDTthreads).  Latest news: r-datatable.com
require(ggplot2)
Loading required package: ggplot2
require(plotly)
Loading required package: plotly

Attaching package: ‘plotly’

The following object is masked from ‘package:ggplot2’:

    last_plot

The following object is masked from ‘package:stats’:

    filter

The following object is masked from ‘package:graphics’:

    layout
require(DT)
Loading required package: DT
require(lmerTest)
Loading required package: lmerTest
Loading required package: lme4
Loading required package: Matrix

Attaching package: ‘lmerTest’

The following object is masked from ‘package:lme4’:

    lmer

The following object is masked from ‘package:stats’:

    step
source("source/functions_may2019.R")
# On Windows set multithread=FALSE----
mt <- TRUE

1 Introduction

C57BL/6 wild-type (WT) and Nrf-2 double-knock-out (KO -/-) mice were given 2-week microbiome stabilization process using AIN93M diet and 8 more weeks to treat with either AIN93M or AIN93M 5% PEITC diet. Fecal samples were collected weekly, immediately frozen in liquid nitrogen and stored at -80oC. Serum, cecal, colon epithelial and whole colon tissues at week 10 were also collected for further analyses. Baseline, week 1 and 4 fecal samples were selected for 16s rRNA sequencing.

This document examines results from the WT mice samples.

We will attampt to answer the following questions:
1. Did microbiome change over time?
2. Was microbiome affected by diet?
3. Was there a difference between the KO and WT?
4. If there was a change in microbiome composition, what functional changes did it carry? What are the essential functions of the bacteria affected by the treatment and how can this be shown in vivo (metabolites, inflammation markers, etc.)?

2 Data preprocessing

2.1 Raw Data

FastQ files were downloaded from this Rutgers Box location. A total of 144 files (2 per sample, pair-ended) and a pair of undetermined reads were downloaded.

2.2 Script

This script (nrf2ubiome_dada2_sep2019_v1.Rmd) was developed using DADA2 Pipeline Tutorial (1.12) with tips and tricks from the University of Maryland Shool of Medicine Institute for Genome Sciences (IGS) Microbiome Analysis Workshop (April 8-11, 2019). The output of the DADA2 script (data_may2019/ps_sep2019.RData) is explored in this document.

3 Meta data: sample description

# Load data----
# Counts
load("data_sep2019/ps_sep2019.RData")
# Taxonomy
load("data_sep2019/taxa.RData")
taxa <- data.table(seq16s = rownames(taxa),
                   taxa)

NOTE: correction to the meta-data! (11/15/2019)

correct_samples <- fread("data_sep2019/16s metadata Sep-2019.csv")
ps_sep2019@sam_data$DSS <- correct_samples$DSS

4 Samples

ps_sep2019@sam_data$Genotype_Week <- paste(ps_sep2019@sam_data$genotype,
                                           ps_sep2019@sam_data$time,
                                           sep = "_")
ps_sep2019@sam_data$ID <- factor(paste0(ps_sep2019@sam_data$mice_num,
                                        ps_sep2019@sam_data$cage))
ps_sep2019@sam_data$TREATMENT <- paste0(ps_sep2019@sam_data$DSS,
                                        ps_sep2019@sam_data$PEITC,
                                        ps_sep2019@sam_data$cranberry)
ps_sep2019@sam_data$TREATMENT <- factor(ps_sep2019@sam_data$TREATMENT,
                                        levels = c("000",
                                                   "100",
                                                   "110",
                                                   "101"),
                                        labels = c("Naive",
                                                   "DSS",
                                                   "DSS+PEITC",
                                                   "DSS+Cranberry"))
samples <- ps_sep2019@sam_data
datatable(samples,
          options = list(pageLength = nrow(samples)))

5 Prune data

The OTUs were mapped to Bacteria (96.07%), Eukaryota (2.95%) and Archea (0.03%) kingdoms, and 75 OTUs (0.95%) undefined.

The total of 7,867 unique sequences were found. Out of those, 7,558 were mapped to bacterial genomes.

dim(ps_sep2019@otu_table@.Data)
[1]   72 7867
# Remove OTU not mapped to Bacteria
ps0 <- subset_taxa(ps_sep2019, 
                   Kingdom == "Bacteria")
dim(ps0@otu_table@.Data)
[1]   72 7558

These 7,247 belonged to 12 Phyla. 311 of the OTUs (or 4.11% of bacterial OTUs) could not be mapped to a Phyla.

t2 <- data.table(table(tax_table(ps0)[, "Phylum"],
                                  exclude = NULL))
t2$V1[is.na(t2$V1)] <- "Unknown"
setorder(t2, -N)
t2[, pct := N/sum(N)]
setorder(t2, -N)
colnames(t2) <- c("Phylum",
                  "Number of OTUs",
                  "Percent of OTUs")
datatable(t2,
          rownames = FALSE,
          caption = "Number of Bacterial OTUs by Phylum",
          class = "cell-border stripe",
          options = list(search = FALSE,
                         pageLength = nrow(t2))) %>%
  formatCurrency(columns = 2,
                 currency = "",
                 mark = ",",
                 digits = 0) %>%
  formatPercentage(columns = 3,
                   digits = 2)

6 OTU table (first 10 rows)

7 Total counts per sample (i.e. sequencing depth)

t1 <- colSums(otu[, 7:ncol(otu)])
t1 <- data.table(SAMPLE_NAME = names(t1),
                 Total = t1)
t2 <- data.table(SAMPLE_NAME = rownames(samples),
                 ID = samples$ID,
                 CAGE = samples$cage,
                 TREATMENT = samples$TREATMENT,
                 Genotype = samples$genotype,
                 WEEK = samples$time)
smpl <- merge(t1,
              t2,
              by = "SAMPLE_NAME")
p1 <- ggplot(smpl,
             aes(x = SAMPLE_NAME,
                 y = Total,
                 fill = TREATMENT,
                 colour = WEEK)) +
  facet_wrap(~ Genotype,
             scale = "free_x") +
  geom_bar(stat = "identity") +
  scale_x_discrete("") +
  scale_y_continuous("Number of Reads") +
  scale_fill_discrete("Treatment") +
  theme(axis.text.x = element_text(angle = 45,
                                   hjust = 1)) 
ggplotly(p1)

8 Richness (Alpha diversity)

Shannon’s diversity index was calculated for each sample and ploted over time using the 7,764 from the 13 Phylum above.

p1 <- plot_richness(ps0,
                    x = "time", 
                    measures = "Shannon") +
  facet_wrap(~ genotype) +
  geom_line(aes(group = ID),
            color = "black") +
  geom_point(aes(fill = TREATMENT),
             shape = 21,
             size = 3,
             color = "black") +
  scale_x_discrete("") +
  theme(axis.text.x = element_text(angle = 30,
                                   hjust = 1,
                                   vjust = 1))
ggplotly(p = p1,
         tooltip = c("ID",
                     "value"))

p1 <- p1 + 
  scale_fill_discrete("") +
  theme(legend.position = "top")
tiff(filename = "tmp/shannon.tiff",
     height = 4,
     width = 5,
     units = "in",
     res = 600,
     compression = "lzw+p")
print(p1)
graphics.off()

Test if the richness changed between the baseline and the week 8.

tmp <- data.table(SAMPLE_NAME = p1$data$samples,
                  Shannon = p1$data$value)
tmp <- merge(smpl,
              tmp,
              by = "SAMPLE_NAME")
tmp$TREATMENT <- factor(tmp$TREATMENT,
                        levels = c("DSS",
                                   "Naive",
                                   "DSS+PEITC",
                                   "DSS+Cranberry"))
tmp <- droplevels(tmp[WEEK != "week1"])
m1 <- lm(Shannon  ~ WEEK*(TREATMENT + Genotype),
         # offset = Total,
         data = tmp)
summary(m1)

Call:
lm(formula = Shannon ~ WEEK * (TREATMENT + Genotype), data = tmp)

Residuals:
      Min        1Q    Median        3Q       Max 
-0.316186 -0.091027  0.007886  0.110704  0.293230 

Coefficients:
                                 Estimate Std. Error t value Pr(>|t|)    
(Intercept)                       5.94987    0.07064  84.233  < 2e-16 ***
WEEKweek8                         0.01158    0.09989   0.116   0.9084    
TREATMENTNaive                    0.14581    0.08935   1.632   0.1109    
TREATMENTDSS+PEITC               -0.03923    0.08935  -0.439   0.6631    
TREATMENTDSS+Cranberry           -0.22582    0.08935  -2.527   0.0158 *  
Genotypewidetype                 -0.54156    0.06318  -8.572 2.06e-10 ***
WEEKweek8:TREATMENTNaive          0.01181    0.12636   0.093   0.9261    
WEEKweek8:TREATMENTDSS+PEITC      0.01652    0.12636   0.131   0.8966    
WEEKweek8:TREATMENTDSS+Cranberry  0.21535    0.12636   1.704   0.0965 .  
WEEKweek8:Genotypewidetype        0.23085    0.08935   2.584   0.0137 *  
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 0.1548 on 38 degrees of freedom
Multiple R-squared:  0.7845,    Adjusted R-squared:  0.7335 
F-statistic: 15.37 on 9 and 38 DF,  p-value: 3.671e-10
m2 <- lmer(Shannon  ~ WEEK*(TREATMENT + Genotype) + (1 | ID),
           # offset = Total,
           data = tmp)
summary(m2)
Linear mixed model fit by REML. t-tests use Satterthwaite's method ['lmerModLmerTest']
Formula: Shannon ~ WEEK * (TREATMENT + Genotype) + (1 | ID)
   Data: tmp

REML criterion at convergence: -22.2

Scaled residuals: 
     Min       1Q   Median       3Q      Max 
-1.53721 -0.47495  0.06753  0.44489  1.53874 

Random effects:
 Groups   Name        Variance Std.Dev.
 ID       (Intercept) 0.01259  0.1122  
 Residual             0.01136  0.1066  
Number of obs: 48, groups:  ID, 24

Fixed effects:
                                 Estimate Std. Error       df t value Pr(>|t|)    
(Intercept)                       5.94987    0.07064 29.76837  84.233  < 2e-16 ***
WEEKweek8                         0.01158    0.06879 19.00000   0.168  0.86814    
TREATMENTNaive                    0.14581    0.08935 29.76837   1.632  0.11322    
TREATMENTDSS+PEITC               -0.03923    0.08935 29.76837  -0.439  0.66379    
TREATMENTDSS+Cranberry           -0.22582    0.08935 29.76837  -2.527  0.01704 *  
Genotypewidetype                 -0.54156    0.06318 29.76837  -8.572 1.55e-09 ***
WEEKweek8:TREATMENTNaive          0.01181    0.08701 19.00000   0.136  0.89350    
WEEKweek8:TREATMENTDSS+PEITC      0.01652    0.08701 19.00000   0.190  0.85139    
WEEKweek8:TREATMENTDSS+Cranberry  0.21535    0.08701 19.00000   2.475  0.02291 *  
WEEKweek8:Genotypewidetype        0.23085    0.06152 19.00000   3.752  0.00135 ** 
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Correlation of Fixed Effects:
                     (Intr) WEEKw8 TREATMENTN TREATMENTDSS+P TREATMENTDSS+C Gntypw WEEK8:TREATMENTN
WEEKweek8            -0.487                                                                        
TREATMENTNv          -0.632  0.308                                                                 
TREATMENTDSS+P       -0.632  0.308  0.500                                                          
TREATMENTDSS+C       -0.632  0.308  0.500      0.500                                               
Gentypwdtyp          -0.447  0.218  0.000      0.000          0.000                                
WEEK8:TREATMENTN      0.308 -0.632 -0.487     -0.243         -0.243          0.000                 
WEEK8:TREATMENTDSS+P  0.308 -0.632 -0.243     -0.487         -0.243          0.000  0.500          
WEEK8:TREATMENTDSS+C  0.308 -0.632 -0.243     -0.243         -0.487          0.000  0.500          
WEEKwk8:Gnt           0.218 -0.447  0.000      0.000          0.000         -0.487  0.000          
                     WEEK8:TREATMENTDSS+P WEEK8:TREATMENTDSS+C
WEEKweek8                                                     
TREATMENTNv                                                   
TREATMENTDSS+P                                                
TREATMENTDSS+C                                                
Gentypwdtyp                                                   
WEEK8:TREATMENTN                                              
WEEK8:TREATMENTDSS+P                                          
WEEK8:TREATMENTDSS+C  0.500                                   
WEEKwk8:Gnt           0.000                0.000              

The results showed that…

9 Remove unmapped OTUs

The 311 unmapped OTUs were removed from further analysis (with 7,247 OTUs left).

ps1 <- subset_taxa(ps0, 
                   !is.na(Phylum))
dim(ps1@otu_table@.Data)
[1]   72 7247

10 Counts at Phylum level

11 Relative abundance (%) at Phylum level

Remove phyla with relative abundance of >= 1% in less than 10% of samples.

t1 <- data.table(Phylum = ra_p$Phylum,
                 `Number of Samples` = rowSums(ra_p[, 2:ncol(ra_p)] >= 0.01))
t1$`Percent Samples` <-  t1$`Number of Samples`/72
setorder(t1, -`Number of Samples`)
datatable(t1,
          rownames = FALSE,
          caption = "Taxonomic  count table",
          class = "cell-border stripe",
          options = list(search = FALSE,
                         pageLength = nrow(t1))) %>%
  formatPercentage(columns = 3,
                   digits = 1)

We will remove Chlamydiae from this analysis.

[1] "Firmicutes, Bacteroidetes, Proteobacteria, Verrucomicrobia, Epsilonbacteraeota, Actinobacteria, Deferribacteres, Patescibacteria, Cyanobacteria"

XX OTUs, down from YY OTUs in the previous table.

12 Relative Abundance in Samples at Different Taxonomic Ranks

12.1 1. Class

mu$Trt_Genotype <- factor(paste(mu$Treatment,
                          mu$Genotype,
                          sep = "_"))
p0 <- ggplot(mu,
             aes(x = Week,
                 y = x,
                 group = Trt_Genotype)) +
  facet_wrap(~ Class,
             scale = "free_y") +
  geom_line(position = position_dodge(0.3)) +
  geom_point(aes(fill = Trt_Genotype),
             shape = 21,
             size = 2,
             alpha = 0.5,
             position = position_dodge(0.3)) +
  scale_x_discrete("") +
  scale_y_continuous("Relative Abundance (%)") +
  theme(legend.position = "top",
        axis.text.x = element_text(angle = 45,
                                   hjust = 1))
tiff(filename = "tmp/wt_class_over_time.tiff",
     height = 5,
     width = 7,
     units = "in",
     res = 600,
     compression = "lzw+p")
print(p0)
graphics.off()
print(p0)

p1 <- ggplot(mu,
             aes(x = x,
                 y = Class,
                 color = Trt_Genotype,
                 shape = Week)) +
  geom_point(size = 3,
             alpha = 0.5) +
  geom_vline(xintercept = 1,
             linetype = "dashed") +
  scale_x_continuous("Relative Abundance (%)") +
  theme(legend.position = "top")
tiff(filename = "tmp/wt_class_ra.tiff",
     height = 4,
     width = 7,
     units = "in",
     res = 600,
     compression = "lzw+p")
print(p1)
graphics.off()
ggplotly(p1)

12.2 2. Order

mu$Trt_Genotype <- factor(paste(mu$Treatment,
                                mu$Genotype,
                                sep = "_"))
p0 <- ggplot(mu,
             aes(x = Week,
                 y = x,
                 group = Trt_Genotype)) +
  facet_wrap(~ Order,
             scale = "free_y") +
  geom_line(position = position_dodge(0.3)) +
  geom_point(aes(fill = Trt_Genotype),
             shape = 21,
             size = 2,
             alpha = 0.5,
             position = position_dodge(0.3)) +
  scale_x_discrete("") +
  scale_y_continuous("Relative Abundance (%)") +
  theme(legend.position = "top",
        axis.text.x = element_text(angle = 45,
                                   hjust = 1))
tiff(filename = "tmp/wt_Order_over_time.tiff",
     height = 5,
     width = 7,
     units = "in",
     res = 600,
     compression = "lzw+p")
print(p0)
graphics.off()
print(p0)

p1 <- ggplot(mu,
             aes(x = x,
                 y = Order,
                 color = Trt_Genotype,
                 shape = Week)) +
  geom_point(size = 3,
             alpha = 0.5) +
  geom_vline(xintercept = 1,
             linetype = "dashed") +
  scale_x_continuous("Relative Abundance (%)") +
  theme(legend.position = "top")
tiff(filename = "tmp/wt_Order_ra.tiff",
     height = 4,
     width = 7,
     units = "in",
     res = 600,
     compression = "lzw+p")
print(p1)
graphics.off()
ggplotly(p1)

12.3 3. Family

NOTE: only the first 24 families had large enough counts - ploting only them.

mu$Trt_Genotype <- factor(paste(mu$Treatment,
                                mu$Genotype,
                                sep = "_"))
mu <- droplevels(mu[levels(mu$Family)[1:24], ])
Error in `[.data.table`(mu, levels(mu$Family)[1:24], ) : 
  When i is a data.table (or character vector), the columns to join by must be specified either using 'on=' argument (see ?data.table) or by keying x (i.e. sorted, and, marked as sorted, see ?setkey). Keyed joins might have further speed benefits on very large data due to x being sorted in RAM.

13 Session Information

sessionInfo()
LS0tCnRpdGxlOiAiRGF0YSBWaXN1YWxpemF0aW9uIG9mIFdUIGFuZCBOcmYyIEtPICgtLy0pIEJMNiBQRUlUQyBvciBDcmFuYmVycnkgVHJlYXRlZCBNaWNlIDE2UyBNaWNyb2Jpb21lIERhdGEgQW5hbHlzaXMsIFNlcHRlbWJlciAyMDE5IEJhdGNoIgpvdXRwdXQ6IAogIGh0bWxfbm90ZWJvb2s6CiAgICB0b2M6IHllcwogICAgdG9jX2Zsb2F0OiB5ZXMKICAgIG51bWJlcl9zZWN0aW9uczogeWVzCiAgICBjb2RlX2ZvbGRpbmc6IGhpZGUKLS0tCkRhdGU6IGByIGRhdGUoKWAgICAgIApTY2llbnRpc3Q6IFtSYW4gWWluXShtYWlsdG86cnkxNDdAc2NhcmxldG1haWwucnV0Z2Vycy5lZHUpICAgICAgClNlcXVlbmNpbmcgKFdha3NtYW4pOiBbRGlieWVuZHUgS3VtYXJdKG1haWx0bzpka0B3YWtzbWFuLnJ1dGdlcnMuZWR1KSAgICAgIApTdGF0aXN0aWNzOiBbRGF2aXQgU2FyZ3N5YW5dKG1haWx0bzpzYXJnZGF2aWRAZ21haWwuY29tKSAgICAgIApQcmluY2lwYWwgSW52ZXN0aWdhdG9yOiBbQWgtTmcgS29uZ10obWFpbHRvOmtvbmd0QHBoYXJtYWN5LnJ1dGdlcnMuZWR1KSAKCmBgYHt9CiMgVGF4b25vbWljIFJhbmtzOgojICoqSyoqaW5nICoqUCoqaGlsbGlwICoqQyoqYW4gbioqTyoqdCAqKkYqKmluZCAqKkcqKnJlZW4gKipTKipvY2tzCiMgKiBLaW5nZG9tICAgICAgICAgICAgICAgIAojICogUGh5bHVtICAgICAgICAgICAgICAgICAgICAKIyAqIENsYXNzICAgICAgICAgICAgICAgICAgIAojICogT3JkZXIgICAgICAgICAgICAgICAgICAgCiMgKiBGYW1pbHkgICAgIAojICogR2VudXMgICAgIAojICogU3BlY2llcyAgCmBgYAoKYGBge3Igc2V0dXB9CiMgb3B0aW9ucyhzdHJpbmdzQXNGYWN0b3JzID0gRkFMU0UsCiMgICAgICAgICBzY2lwZW4gPSA5OTkpCgojICMgSW5jcmVhc2UgbW1lbW9yeSBzaXplIHRvIDY0IEdiLS0tLQojIGludmlzaWJsZSh1dGlsczo6bWVtb3J5LmxpbWl0KDY1NTM2KSkKCgojIHN0cihrbml0cjo6b3B0c19jaHVuayRnZXQoKSkKIyAjIE5PVEU6IHRoZSBiZWxvdyBkb2VzIG5vdCB3b3JrIQojIGtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gRkFMU0UsIAojICAgICAgICAgICAgICAgICAgICAgICBtZXNzYWdlID0gRkFMU0UsCiMgICAgICAgICAgICAgICAgICAgICAgIHdhcm5pbmcgPSBGQUxTRSwKIyAgICAgICAgICAgICAgICAgICAgICAgZXJyb3IgPSBGQUxTRSkKCiMgcmVxdWlyZShrbml0cikKIyByZXF1aXJlKGthYmxlRXh0cmEpCnJlcXVpcmUocGh5bG9zZXEpCiMgcmVxdWlyZShzaGlueSkKCnJlcXVpcmUoZGF0YS50YWJsZSkKcmVxdWlyZShnZ3Bsb3QyKQpyZXF1aXJlKHBsb3RseSkKcmVxdWlyZShEVCkKcmVxdWlyZShsbWVyVGVzdCkKCnNvdXJjZSgic291cmNlL2Z1bmN0aW9uc19tYXkyMDE5LlIiKQoKIyBPbiBXaW5kb3dzIHNldCBtdWx0aXRocmVhZD1GQUxTRS0tLS0KbXQgPC0gVFJVRQpgYGAKCiMgSW50cm9kdWN0aW9uCkM1N0JMLzYgd2lsZC10eXBlIChXVCkgYW5kIE5yZi0yIGRvdWJsZS1rbm9jay1vdXQgKEtPIC0vLSkgbWljZSB3ZXJlIGdpdmVuIDItd2VlayBtaWNyb2Jpb21lIHN0YWJpbGl6YXRpb24gcHJvY2VzcyB1c2luZyBBSU45M00gZGlldCBhbmQgOCBtb3JlIHdlZWtzIHRvIHRyZWF0IHdpdGggZWl0aGVyIEFJTjkzTSBvciBBSU45M00gNSUgUEVJVEMgZGlldC4gRmVjYWwgc2FtcGxlcyB3ZXJlIGNvbGxlY3RlZCB3ZWVrbHksIGltbWVkaWF0ZWx5IGZyb3plbiBpbiBsaXF1aWQgbml0cm9nZW4gYW5kIHN0b3JlZCBhdCAtODBeb15DLiBTZXJ1bSwgY2VjYWwsIGNvbG9uIGVwaXRoZWxpYWwgYW5kIHdob2xlIGNvbG9uIHRpc3N1ZXMgYXQgd2VlayAxMCB3ZXJlIGFsc28gY29sbGVjdGVkIGZvciBmdXJ0aGVyIGFuYWx5c2VzLiBCYXNlbGluZSwgd2VlayAxIGFuZCA0IGZlY2FsIHNhbXBsZXMgd2VyZSBzZWxlY3RlZCBmb3IgMTZzIHJSTkEgc2VxdWVuY2luZy4gIAogIApUaGlzIGRvY3VtZW50IGV4YW1pbmVzIHJlc3VsdHMgZnJvbSB0aGUgV1QgbWljZSBzYW1wbGVzLiAgCiAgCldlIHdpbGwgYXR0YW1wdCB0byBhbnN3ZXIgdGhlIGZvbGxvd2luZyBxdWVzdGlvbnM6ICAKMS4gRGlkIG1pY3JvYmlvbWUgY2hhbmdlIG92ZXIgdGltZT8gIAoyLiBXYXMgbWljcm9iaW9tZSBhZmZlY3RlZCBieSBkaWV0PyAgCjMuIFdhcyB0aGVyZSBhIGRpZmZlcmVuY2UgYmV0d2VlbiB0aGUgS08gYW5kIFdUPyAgCjQuIElmIHRoZXJlIHdhcyBhIGNoYW5nZSBpbiBtaWNyb2Jpb21lIGNvbXBvc2l0aW9uLCB3aGF0IGZ1bmN0aW9uYWwgY2hhbmdlcyBkaWQgaXQgY2Fycnk/IFdoYXQgYXJlIHRoZSBlc3NlbnRpYWwgZnVuY3Rpb25zIG9mIHRoZSBiYWN0ZXJpYSBhZmZlY3RlZCBieSB0aGUgdHJlYXRtZW50IGFuZCBob3cgY2FuIHRoaXMgYmUgc2hvd24gaW4gdml2byAobWV0YWJvbGl0ZXMsIGluZmxhbW1hdGlvbiBtYXJrZXJzLCBldGMuKT8KCiMgRGF0YSBwcmVwcm9jZXNzaW5nCiMjIFJhdyBEYXRhIApGYXN0USBmaWxlcyB3ZXJlIGRvd25sb2FkZWQgZnJvbSBbdGhpcyBSdXRnZXJzIEJveCBsb2NhdGlvbl0oaHR0cHM6Ly9ydXRnZXJzLmFwcC5ib3guY29tL2ZvbGRlci85MDE0MzQ2MjI5MSkuIEEgdG90YWwgb2YgMTQ0IGZpbGVzICgyIHBlciBzYW1wbGUsIHBhaXItZW5kZWQpIGFuZCBhIHBhaXIgb2YgdW5kZXRlcm1pbmVkIHJlYWRzIHdlcmUgZG93bmxvYWRlZC4gCgojIyBTY3JpcHQKVGhpcyBzY3JpcHQgKCoqKm5yZjJ1YmlvbWVfZGFkYTJfc2VwMjAxOV92MS5SbWQqKiopIHdhcyBkZXZlbG9wZWQgdXNpbmcgW0RBREEyIFBpcGVsaW5lIFR1dG9yaWFsICgxLjEyKV0oaHR0cHM6Ly9iZW5qam5lYi5naXRodWIuaW8vZGFkYTIvdHV0b3JpYWwuaHRtbCkgd2l0aCB0aXBzIGFuZCB0cmlja3MgZnJvbSB0aGUgW1VuaXZlcnNpdHkgb2YgTWFyeWxhbmQgU2hvb2wgb2YgTWVkaWNpbmUgSW5zdGl0dXRlIGZvciBHZW5vbWUgU2NpZW5jZXMgKElHUyldKGh0dHA6Ly93d3cuaWdzLnVtYXJ5bGFuZC5lZHUvKSBbTWljcm9iaW9tZSBBbmFseXNpcyBXb3Jrc2hvcCAoQXByaWwgOC0xMSwgMjAxOSldKGh0dHA6Ly93d3cuaWdzLnVtYXJ5bGFuZC5lZHUvZWR1Y2F0aW9uL3drc2hwX21ldGFnZW5vbWUucGhwKS4gVGhlIG91dHB1dCBvZiB0aGUgREFEQTIgc2NyaXB0ICgqKipkYXRhX21heTIwMTkvcHNfc2VwMjAxOS5SRGF0YSoqKikgaXMgZXhwbG9yZWQgaW4gdGhpcyBkb2N1bWVudC4KCiMgTWV0YSBkYXRhOiBzYW1wbGUgZGVzY3JpcHRpb24KYGBge3IgZGF0YX0KIyBMb2FkIGRhdGEtLS0tCiMgQ291bnRzCmxvYWQoImRhdGFfc2VwMjAxOS9wc19zZXAyMDE5LlJEYXRhIikKCiMgVGF4b25vbXkKbG9hZCgiZGF0YV9zZXAyMDE5L3RheGEuUkRhdGEiKQp0YXhhIDwtIGRhdGEudGFibGUoc2VxMTZzID0gcm93bmFtZXModGF4YSksCiAgICAgICAgICAgICAgICAgICB0YXhhKQpgYGAKCioqTk9URTogY29ycmVjdGlvbiB0byB0aGUgbWV0YS1kYXRhISoqICgxMS8xNS8yMDE5KQpgYGB7ciBjb3JyZWN0X21ldGFfZGF0YX0KY29ycmVjdF9zYW1wbGVzIDwtIGZyZWFkKCJkYXRhX3NlcDIwMTkvMTZzIG1ldGFkYXRhIFNlcC0yMDE5LmNzdiIpCnBzX3NlcDIwMTlAc2FtX2RhdGEkRFNTIDwtIGNvcnJlY3Rfc2FtcGxlcyREU1MKYGBgCgojIFNhbXBsZXMKYGBge3Igc2FtcGxlc30KcHNfc2VwMjAxOUBzYW1fZGF0YSRHZW5vdHlwZV9XZWVrIDwtIHBhc3RlKHBzX3NlcDIwMTlAc2FtX2RhdGEkZ2Vub3R5cGUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwc19zZXAyMDE5QHNhbV9kYXRhJHRpbWUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZXAgPSAiXyIpCnBzX3NlcDIwMTlAc2FtX2RhdGEkSUQgPC0gZmFjdG9yKHBhc3RlMChwc19zZXAyMDE5QHNhbV9kYXRhJG1pY2VfbnVtLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHNfc2VwMjAxOUBzYW1fZGF0YSRjYWdlKSkKCnBzX3NlcDIwMTlAc2FtX2RhdGEkVFJFQVRNRU5UIDwtIHBhc3RlMChwc19zZXAyMDE5QHNhbV9kYXRhJERTUywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBzX3NlcDIwMTlAc2FtX2RhdGEkUEVJVEMsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwc19zZXAyMDE5QHNhbV9kYXRhJGNyYW5iZXJyeSkKcHNfc2VwMjAxOUBzYW1fZGF0YSRUUkVBVE1FTlQgPC0gZmFjdG9yKHBzX3NlcDIwMTlAc2FtX2RhdGEkVFJFQVRNRU5ULAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWxzID0gYygiMDAwIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIjEwMCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICIxMTAiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiMTAxIiksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBjKCJOYWl2ZSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJEU1MiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiRFNTK1BFSVRDIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkRTUytDcmFuYmVycnkiKSkKCnNhbXBsZXMgPC0gcHNfc2VwMjAxOUBzYW1fZGF0YQpkYXRhdGFibGUoc2FtcGxlcywKICAgICAgICAgIG9wdGlvbnMgPSBsaXN0KHBhZ2VMZW5ndGggPSBucm93KHNhbXBsZXMpKSkKYGBgCgojIFBydW5lIGRhdGEKVGhlIE9UVXMgd2VyZSBtYXBwZWQgdG8gQmFjdGVyaWEgKDk2LjA3JSksIEV1a2FyeW90YSAoMi45NSUpIGFuZCBBcmNoZWEgKDAuMDMlKSBraW5nZG9tcywgYW5kICA3NSBPVFVzICgwLjk1JSkgdW5kZWZpbmVkLiAKCmBgYHtyIGNoZWNrX21hcHBpbmdfa2luZ2RvbSwgd2FybmluZyA9IEZBTFNFLCBlY2hvID0gRkFMU0UsIG1lc3NhZ2UgPSBGQUxTRX0KdDEgPC0gZGF0YS50YWJsZSh0YWJsZSh0YXhfdGFibGUocHNfc2VwMjAxOSlbLCAiS2luZ2RvbSJdLAogICAgICAgICAgICAgICAgICAgICAgIGV4Y2x1ZGUgPSBOVUxMKSkKdDEkVjFbaXMubmEodDEkVjEpXSA8LSAiVW5rbm93biIKCnQxWywgcGN0IDo9IE4vc3VtKE4pXQpzZXRvcmRlcih0MSwgLU4pCgpjb2xuYW1lcyh0MSkgPC0gYygiS2luZ2RvbSIsCiAgICAgICAgICAgICAgICAgICJOdW1iZXIgb2YgT1RVcyIsCiAgICAgICAgICAgICAgICAgICJQZXJjZW50IG9mIE9UVXMiKQpkYXRhdGFibGUodDEsCiAgICAgICAgICByb3duYW1lcyA9IEZBTFNFLAogICAgICAgICAgY2FwdGlvbiA9ICJOdW1iZXIgb2YgT1RVcyBieSBLaW5nZG9tIiwKICAgICAgICAgIGNsYXNzID0gImNlbGwtYm9yZGVyIHN0cmlwZSIsCiAgICAgICAgICBvcHRpb25zID0gbGlzdChzZWFyY2ggPSBGQUxTRSwKICAgICAgICAgICAgICAgICAgICAgICAgIHBhZ2VMZW5ndGggPSBucm93KHQxKSkpICU+JQogIGZvcm1hdEN1cnJlbmN5KGNvbHVtbnMgPSAyLAogICAgICAgICAgICAgICAgIGN1cnJlbmN5ID0gIiIsCiAgICAgICAgICAgICAgICAgbWFyayA9ICIsIiwKICAgICAgICAgICAgICAgICBkaWdpdHMgPSAwKSAlPiUKICBmb3JtYXRQZXJjZW50YWdlKGNvbHVtbnMgPSAzLAogICAgICAgICAgICAgICAgICAgZGlnaXRzID0gMikKYGBgCgpUaGUgdG90YWwgb2YgNyw4NjcgdW5pcXVlIHNlcXVlbmNlcyB3ZXJlIGZvdW5kLiBPdXQgb2YgdGhvc2UsIDcsNTU4IHdlcmUgbWFwcGVkIHRvIGJhY3RlcmlhbCBnZW5vbWVzLiAKCmBgYHtyIGtlZXBfYmFjdGVyaWF9CmRpbShwc19zZXAyMDE5QG90dV90YWJsZUAuRGF0YSkKCiMgUmVtb3ZlIE9UVSBub3QgbWFwcGVkIHRvIEJhY3RlcmlhCnBzMCA8LSBzdWJzZXRfdGF4YShwc19zZXAyMDE5LCAKICAgICAgICAgICAgICAgICAgIEtpbmdkb20gPT0gIkJhY3RlcmlhIikKZGltKHBzMEBvdHVfdGFibGVALkRhdGEpCmBgYAogIApUaGVzZSA3LDI0NyBiZWxvbmdlZCB0byAxMiBQaHlsYS4gMzExIG9mIHRoZSBPVFVzIChvciA0LjExJSBvZiBiYWN0ZXJpYWwgT1RVcykgY291bGQgbm90IGJlIG1hcHBlZCB0byBhIFBoeWxhLgoKYGBge3IgcGh5bHVtX21hcHBpbmd9CnQyIDwtIGRhdGEudGFibGUodGFibGUodGF4X3RhYmxlKHBzMClbLCAiUGh5bHVtIl0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBleGNsdWRlID0gTlVMTCkpCnQyJFYxW2lzLm5hKHQyJFYxKV0gPC0gIlVua25vd24iCnNldG9yZGVyKHQyLCAtTikKdDJbLCBwY3QgOj0gTi9zdW0oTildCnNldG9yZGVyKHQyLCAtTikKCmNvbG5hbWVzKHQyKSA8LSBjKCJQaHlsdW0iLAogICAgICAgICAgICAgICAgICAiTnVtYmVyIG9mIE9UVXMiLAogICAgICAgICAgICAgICAgICAiUGVyY2VudCBvZiBPVFVzIikKCmRhdGF0YWJsZSh0MiwKICAgICAgICAgIHJvd25hbWVzID0gRkFMU0UsCiAgICAgICAgICBjYXB0aW9uID0gIk51bWJlciBvZiBCYWN0ZXJpYWwgT1RVcyBieSBQaHlsdW0iLAogICAgICAgICAgY2xhc3MgPSAiY2VsbC1ib3JkZXIgc3RyaXBlIiwKICAgICAgICAgIG9wdGlvbnMgPSBsaXN0KHNlYXJjaCA9IEZBTFNFLAogICAgICAgICAgICAgICAgICAgICAgICAgcGFnZUxlbmd0aCA9IG5yb3codDIpKSkgJT4lCiAgZm9ybWF0Q3VycmVuY3koY29sdW1ucyA9IDIsCiAgICAgICAgICAgICAgICAgY3VycmVuY3kgPSAiIiwKICAgICAgICAgICAgICAgICBtYXJrID0gIiwiLAogICAgICAgICAgICAgICAgIGRpZ2l0cyA9IDApICU+JQogIGZvcm1hdFBlcmNlbnRhZ2UoY29sdW1ucyA9IDMsCiAgICAgICAgICAgICAgICAgICBkaWdpdHMgPSAyKQpgYGAKCiMgT1RVIHRhYmxlIChmaXJzdCAxMCByb3dzKQpgYGB7ciBvdHVfdGFibGUsIHdhcm5pbmc9RkFMU0UsZWNobz1GQUxTRSxtZXNzYWdlPUZBTFNFfQpvdHUgPC0gZGF0YS50YWJsZShwczBAdGF4X3RhYmxlQC5EYXRhLAogICAgICAgICAgICAgICAgICB0KHBzMEBvdHVfdGFibGVALkRhdGEpKQpkYXRhdGFibGUoaGVhZChvdHUsIDEwKSwKICAgICAgICAgIHJvd25hbWVzID0gRkFMU0UsCiAgICAgICAgICBjYXB0aW9uID0gIlRheG9ub21pYyAgY291bnQgdGFibGUiLAogICAgICAgICAgY2xhc3MgPSAiY2VsbC1ib3JkZXIgc3RyaXBlIiwKICAgICAgICAgIG9wdGlvbnMgPSBsaXN0KHNlYXJjaCA9IEZBTFNFLAogICAgICAgICAgICAgICAgICAgICAgICAgcGFnZUxlbmd0aCA9IDEwKSkgJT4lCiAgZm9ybWF0Q3VycmVuY3koY29sdW1ucyA9IDc6MzYsCiAgICAgICAgICAgICAgICAgY3VycmVuY3kgPSAiIiwKICAgICAgICAgICAgICAgICBtYXJrID0gIiwiLAogICAgICAgICAgICAgICAgIGRpZ2l0cyA9IDApCmBgYAoKIyBUb3RhbCBjb3VudHMgcGVyIHNhbXBsZSAoaS5lLiBzZXF1ZW5jaW5nIGRlcHRoKQpgYGB7ciBzZXFfZGVwdGgsIGZpZy53aWR0aCA9IDEwLGZpZy5oZWlnaHQgPSA1fQp0MSA8LSBjb2xTdW1zKG90dVssIDc6bmNvbChvdHUpXSkKdDEgPC0gZGF0YS50YWJsZShTQU1QTEVfTkFNRSA9IG5hbWVzKHQxKSwKICAgICAgICAgICAgICAgICBUb3RhbCA9IHQxKQoKdDIgPC0gZGF0YS50YWJsZShTQU1QTEVfTkFNRSA9IHJvd25hbWVzKHNhbXBsZXMpLAogICAgICAgICAgICAgICAgIElEID0gc2FtcGxlcyRJRCwKICAgICAgICAgICAgICAgICBDQUdFID0gc2FtcGxlcyRjYWdlLAogICAgICAgICAgICAgICAgIFRSRUFUTUVOVCA9IHNhbXBsZXMkVFJFQVRNRU5ULAogICAgICAgICAgICAgICAgIEdlbm90eXBlID0gc2FtcGxlcyRnZW5vdHlwZSwKICAgICAgICAgICAgICAgICBXRUVLID0gc2FtcGxlcyR0aW1lKQoKc21wbCA8LSBtZXJnZSh0MSwKICAgICAgICAgICAgICB0MiwKICAgICAgICAgICAgICBieSA9ICJTQU1QTEVfTkFNRSIpCgpwMSA8LSBnZ3Bsb3Qoc21wbCwKICAgICAgICAgICAgIGFlcyh4ID0gU0FNUExFX05BTUUsCiAgICAgICAgICAgICAgICAgeSA9IFRvdGFsLAogICAgICAgICAgICAgICAgIGZpbGwgPSBUUkVBVE1FTlQsCiAgICAgICAgICAgICAgICAgY29sb3VyID0gV0VFSykpICsKICBmYWNldF93cmFwKH4gR2Vub3R5cGUsCiAgICAgICAgICAgICBzY2FsZSA9ICJmcmVlX3giKSArCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIpICsKICBzY2FsZV94X2Rpc2NyZXRlKCIiKSArCiAgc2NhbGVfeV9jb250aW51b3VzKCJOdW1iZXIgb2YgUmVhZHMiKSArCiAgc2NhbGVfZmlsbF9kaXNjcmV0ZSgiVHJlYXRtZW50IikgKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaGp1c3QgPSAxKSkgCmdncGxvdGx5KHAxKQpgYGAKCiMgUmljaG5lc3MgKEFscGhhIGRpdmVyc2l0eSkKU2hhbm5vbidzIGRpdmVyc2l0eSBpbmRleCB3YXMgY2FsY3VsYXRlZCBmb3IgZWFjaCBzYW1wbGUgYW5kIHBsb3RlZCBvdmVyIHRpbWUgdXNpbmcgdGhlIDcsNzY0IGZyb20gdGhlIDEzIFBoeWx1bSBhYm92ZS4KCmBgYHtyIHJpY2huZXNzLCBmaWcud2lkdGggPSAxMCxmaWcuaGVpZ2h0ID0gNX0KcDEgPC0gcGxvdF9yaWNobmVzcyhwczAsCiAgICAgICAgICAgICAgICAgICAgeCA9ICJ0aW1lIiwgCiAgICAgICAgICAgICAgICAgICAgbWVhc3VyZXMgPSAiU2hhbm5vbiIpICsKICBmYWNldF93cmFwKH4gZ2Vub3R5cGUpICsKICBnZW9tX2xpbmUoYWVzKGdyb3VwID0gSUQpLAogICAgICAgICAgICBjb2xvciA9ICJibGFjayIpICsKICBnZW9tX3BvaW50KGFlcyhmaWxsID0gVFJFQVRNRU5UKSwKICAgICAgICAgICAgIHNoYXBlID0gMjEsCiAgICAgICAgICAgICBzaXplID0gMywKICAgICAgICAgICAgIGNvbG9yID0gImJsYWNrIikgKwogIHNjYWxlX3hfZGlzY3JldGUoIiIpICsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDMwLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhqdXN0ID0gMSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2anVzdCA9IDEpKQoKZ2dwbG90bHkocCA9IHAxLAogICAgICAgICB0b29sdGlwID0gYygiSUQiLAogICAgICAgICAgICAgICAgICAgICAidmFsdWUiKSkKCnAxIDwtIHAxICsgCiAgc2NhbGVfZmlsbF9kaXNjcmV0ZSgiIikgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJ0b3AiKQoKdGlmZihmaWxlbmFtZSA9ICJ0bXAvc2hhbm5vbi50aWZmIiwKICAgICBoZWlnaHQgPSA0LAogICAgIHdpZHRoID0gNSwKICAgICB1bml0cyA9ICJpbiIsCiAgICAgcmVzID0gNjAwLAogICAgIGNvbXByZXNzaW9uID0gImx6dytwIikKcHJpbnQocDEpCmdyYXBoaWNzLm9mZigpCmBgYAoKVGVzdCBpZiB0aGUgcmljaG5lc3MgY2hhbmdlZCBiZXR3ZWVuIHRoZSBiYXNlbGluZSBhbmQgdGhlIHdlZWsgOC4KYGBge3IgbG1fcmljaG5lc3N9CnRtcCA8LSBkYXRhLnRhYmxlKFNBTVBMRV9OQU1FID0gcDEkZGF0YSRzYW1wbGVzLAogICAgICAgICAgICAgICAgICBTaGFubm9uID0gcDEkZGF0YSR2YWx1ZSkKCnRtcCA8LSBtZXJnZShzbXBsLAogICAgICAgICAgICAgIHRtcCwKICAgICAgICAgICAgICBieSA9ICJTQU1QTEVfTkFNRSIpCgp0bXAkVFJFQVRNRU5UIDwtIGZhY3Rvcih0bXAkVFJFQVRNRU5ULAogICAgICAgICAgICAgICAgICAgICAgICBsZXZlbHMgPSBjKCJEU1MiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJOYWl2ZSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkRTUytQRUlUQyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkRTUytDcmFuYmVycnkiKSkKCnRtcCA8LSBkcm9wbGV2ZWxzKHRtcFtXRUVLICE9ICJ3ZWVrMSJdKQoKbTEgPC0gbG0oU2hhbm5vbiAgfiBXRUVLKihUUkVBVE1FTlQgKyBHZW5vdHlwZSksCiAgICAgICAgICMgb2Zmc2V0ID0gVG90YWwsCiAgICAgICAgIGRhdGEgPSB0bXApCnN1bW1hcnkobTEpCmBgYAoKYGBge3IgbG1lcl9yaWNobmVzc30KbTIgPC0gbG1lcihTaGFubm9uICB+IFdFRUsqKFRSRUFUTUVOVCArIEdlbm90eXBlKSArICgxIHwgSUQpLAogICAgICAgICAgICMgb2Zmc2V0ID0gVG90YWwsCiAgICAgICAgICAgZGF0YSA9IHRtcCkKc3VtbWFyeShtMikKYGBgCiAgClRoZSByZXN1bHRzIHNob3dlZCB0aGF0Li4uCiAgCiMgUmVtb3ZlIHVubWFwcGVkIE9UVXMKVGhlIDMxMSB1bm1hcHBlZCBPVFVzIHdlcmUgcmVtb3ZlZCBmcm9tIGZ1cnRoZXIgYW5hbHlzaXMgKHdpdGggNywyNDcgT1RVcyBsZWZ0KS4KYGBge3IgcmVtb3ZlX3VubWFwcGVkX290dV9waHlsdW19CnBzMSA8LSBzdWJzZXRfdGF4YShwczAsIAogICAgICAgICAgICAgICAgICAgIWlzLm5hKFBoeWx1bSkpCmRpbShwczFAb3R1X3RhYmxlQC5EYXRhKQpgYGAKCiMgQ291bnRzIGF0IFBoeWx1bSBsZXZlbApgYGB7ciBjb3VudHNfcCwgd2FybmluZz1GQUxTRSxlY2hvPUZBTFNFLG1lc3NhZ2U9RkFMU0V9CmNvdW50c19wIDwtIGNvdW50c19ieV90YXhfcmFuayhkdDEgPSBvdHUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhZ2dyX2J5ID0gIlBoeWx1bSIpCnNldG9yZGVyKGNvdW50c19wLCAtYDE5MDkxOS0wMWApCmRhdGF0YWJsZShjb3VudHNfcCwKICAgICAgICAgIHJvd25hbWVzID0gRkFMU0UsCiAgICAgICAgICBjYXB0aW9uID0gIlRheG9ub21pYyAgY291bnQgdGFibGUiLAogICAgICAgICAgY2xhc3MgPSAiY2VsbC1ib3JkZXIgc3RyaXBlIiwKICAgICAgICAgIG9wdGlvbnMgPSBsaXN0KHNlYXJjaCA9IEZBTFNFLAogICAgICAgICAgICAgICAgICAgICAgICAgcGFnZUxlbmd0aCA9IG5yb3coY291bnRzX3ApKSkgJT4lCiAgZm9ybWF0Q3VycmVuY3koY29sdW1ucyA9IDI6bmNvbChjb3VudHNfcCksCiAgICAgICAgICAgICAgICAgY3VycmVuY3kgPSAiIiwKICAgICAgICAgICAgICAgICBtYXJrID0gIiwiLAogICAgICAgICAgICAgICAgIGRpZ2l0cyA9IDApCmBgYAoKIyBSZWxhdGl2ZSBhYnVuZGFuY2UgKCUpIGF0IFBoeWx1bSBsZXZlbApgYGB7ciByYV9wLCB3YXJuaW5nPUZBTFNFLGVjaG89RkFMU0UsbWVzc2FnZT1GQUxTRX0KcmFfcCA8LSByYV9ieV90YXhfcmFuayhjb3VudHMgPSBjb3VudHNfcCwKICAgICAgICAgICAgICAgICAgICAgICBwY3QgPSBGQUxTRSwKICAgICAgICAgICAgICAgICAgICAgICBkaWdpdCA9IDQpCgpkYXRhdGFibGUocmFfcCwKICAgICAgICAgIHJvd25hbWVzID0gRkFMU0UsCiAgICAgICAgICBjYXB0aW9uID0gIlRheG9ub21pYyAgY291bnQgdGFibGUiLAogICAgICAgICAgY2xhc3MgPSAiY2VsbC1ib3JkZXIgc3RyaXBlIiwKICAgICAgICAgIG9wdGlvbnMgPSBsaXN0KHNlYXJjaCA9IEZBTFNFLAogICAgICAgICAgICAgICAgICAgICAgICAgcGFnZUxlbmd0aCA9IG5yb3cocmFfcCkpKSAlPiUKICBmb3JtYXRQZXJjZW50YWdlKGNvbHVtbnMgPSAyOm5jb2woY291bnRzX3ApLAogICAgICAgICAgICAgICAgICAgZGlnaXRzID0gMikKYGBgCgpSZW1vdmUgcGh5bGEgd2l0aCByZWxhdGl2ZSBhYnVuZGFuY2Ugb2YgPj0gMSUgaW4gbGVzcyB0aGFuIDEwJSBvZiBzYW1wbGVzLgoKYGBge3IgcHJldl9wfQp0MSA8LSBkYXRhLnRhYmxlKFBoeWx1bSA9IHJhX3AkUGh5bHVtLAogICAgICAgICAgICAgICAgIGBOdW1iZXIgb2YgU2FtcGxlc2AgPSByb3dTdW1zKHJhX3BbLCAyOm5jb2wocmFfcCldID49IDAuMDEpKQp0MSRgUGVyY2VudCBTYW1wbGVzYCA8LSAgdDEkYE51bWJlciBvZiBTYW1wbGVzYC83MgoKc2V0b3JkZXIodDEsIC1gTnVtYmVyIG9mIFNhbXBsZXNgKQpkYXRhdGFibGUodDEsCiAgICAgICAgICByb3duYW1lcyA9IEZBTFNFLAogICAgICAgICAgY2FwdGlvbiA9ICJUYXhvbm9taWMgIGNvdW50IHRhYmxlIiwKICAgICAgICAgIGNsYXNzID0gImNlbGwtYm9yZGVyIHN0cmlwZSIsCiAgICAgICAgICBvcHRpb25zID0gbGlzdChzZWFyY2ggPSBGQUxTRSwKICAgICAgICAgICAgICAgICAgICAgICAgIHBhZ2VMZW5ndGggPSBucm93KHQxKSkpICU+JQogIGZvcm1hdFBlcmNlbnRhZ2UoY29sdW1ucyA9IDMsCiAgICAgICAgICAgICAgICAgICBkaWdpdHMgPSAxKQpgYGAKCldlIHdpbGwgcmVtb3ZlIENobGFteWRpYWUgZnJvbSB0aGlzIGFuYWx5c2lzLgoKYGBge3Iga2VlcF82X3BoeWxhLCB3YXJuaW5nPUZBTFNFLGVjaG89RkFMU0UsbWVzc2FnZT1GQUxTRX0Ka2VlcF9wIDwtIHQxJFBoeWx1bVt0MSRgUGVyY2VudCBTYW1wbGVzYCA+PSAwLjFdCiMgIyBLZWVwIGFsbAojIGtlZXBfcCA8LSB0MSRQaHlsdW0KCnBhc3RlMChrZWVwX3AsIGNvbGxhcHNlID0gIiwgIikKCnBzMSA8LSBzdWJzZXRfdGF4YShwczAsIAogICAgICAgICAgICAgICAgICAgUGh5bHVtICVpbiUga2VlcF9wICkKb3R1MSA8LSBkYXRhLnRhYmxlKHBzMUB0YXhfdGFibGVALkRhdGEsCiAgICAgICAgICAgICAgICAgICB0KHBzMUBvdHVfdGFibGVALkRhdGEpKQoKZGF0YXRhYmxlKGhlYWQob3R1MSwgMTApLAogICAgICAgICAgcm93bmFtZXMgPSBGQUxTRSwKICAgICAgICAgIGNhcHRpb24gPSAiVGF4b25vbWljICBjb3VudCB0YWJsZSIsCiAgICAgICAgICBjbGFzcyA9ICJjZWxsLWJvcmRlciBzdHJpcGUiLAogICAgICAgICAgb3B0aW9ucyA9IGxpc3Qoc2VhcmNoID0gRkFMU0UsCiAgICAgICAgICAgICAgICAgICAgICAgICBwYWdlTGVuZ3RoID0gMTApKSAlPiUKICBmb3JtYXRDdXJyZW5jeShjb2x1bW5zID0gNzpuY29sKG90dTEpLAogICAgICAgICAgICAgICAgIGN1cnJlbmN5ID0gIiIsCiAgICAgICAgICAgICAgICAgbWFyayA9ICIsIiwKICAgICAgICAgICAgICAgICBkaWdpdHMgPSAwKQpgYGAKClhYIE9UVXMsIGRvd24gZnJvbSBZWSBPVFVzIGluIHRoZSBwcmV2aW91cyB0YWJsZS4KCgojIFJlbGF0aXZlIEFidW5kYW5jZSBpbiBTYW1wbGVzIGF0IERpZmZlcmVudCBUYXhvbm9taWMgUmFua3MKIyMgMS4gQ2xhc3MKYGBge3IgY291bnRzX2MsIHdhcm5pbmc9RkFMU0UsZWNobz1GQUxTRSxtZXNzYWdlPUZBTFNFLGZpZy53aWR0aD0xNSxmaWcuaGVpZ2h0PTE1fQpjb3VudHNfYyA8LSBjb3VudHNfYnlfdGF4X3JhbmsoZHQxID0gb3R1MSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFnZ3JfYnkgPSAiQ2xhc3MiKQpyYV9jIDwtIHJhX2J5X3RheF9yYW5rKGNvdW50c19jKQoKdGF4LnJhbmtzIDwtIHVuaXF1ZShvdHUxWywgYygiUGh5bHVtIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiQ2xhc3MiKV0pCgpyYV9jIDwtIG1lcmdlKHRheC5yYW5rcywKICAgICAgICAgICAgICByYV9jLAogICAgICAgICAgICAgIGJ5ID0gIkNsYXNzIikKCnRvdGFsIDwtIHJvd1N1bXMocmFfY1ssIDM6bmNvbChyYV9jKV0pCgpyYV9jJENsYXNzIDwtIGZhY3RvcihyYV9jJENsYXNzLAogICAgICAgICAgICAgICAgICAgICBsZXZlbHMgPSByYV9jJENsYXNzW29yZGVyKHRvdGFsKV0pCgpyYV9jJFBoeWx1bSA8LSBmYWN0b3IocmFfYyRQaHlsdW0sCiAgICAgICAgICAgICAgICAgICAgICBsZXZlbHMgPSB1bmlxdWUocmFfYyRQaHlsdW1bb3JkZXIodG90YWwpXSkpCnRtcCA8LSBtZWx0LmRhdGEudGFibGUoZGF0YSA9IHJhX2MsCiAgICAgICAgICAgICAgICAgICAgICAgaWQudmFycyA9IDE6MiwKICAgICAgICAgICAgICAgICAgICAgICBtZWFzdXJlLnZhcnMgPSAzOm5jb2woY291bnRzX2MpLAogICAgICAgICAgICAgICAgICAgICAgIHZhcmlhYmxlLm5hbWUgPSAiU0FNUExFX05BTUUiLAogICAgICAgICAgICAgICAgICAgICAgIHZhbHVlLm5hbWUgPSAiUkEiKQoKdG1wIDwtIG1lcmdlKGRhdGEudGFibGUoU0FNUExFX05BTUUgPSBzbXBsJFNBTVBMRV9OQU1FLAogICAgICAgICAgICAgICAgICAgICAgICBXRUVLID0gc21wbCRXRUVLLAogICAgICAgICAgICAgICAgICAgICAgICBUUkVBVE1FTlQgPSBzbXBsJFRSRUFUTUVOVCwKICAgICAgICAgICAgICAgICAgICAgICAgR2Vub3R5cGUgPSBzbXBsJEdlbm90eXBlKSwKICAgICAgICAgICAgIHRtcCwKICAgICAgICAgICAgIGJ5ID0gIlNBTVBMRV9OQU1FIikKCiMgUGxvdCBzYW1wbGVzCnAxIDwtIGdncGxvdCh0bXAsCiAgICAgICAgICAgICBhZXMoeCA9IFNBTVBMRV9OQU1FLAogICAgICAgICAgICAgICAgIHkgPSBSQSwKICAgICAgICAgICAgICAgICBmaWxsID0gQ2xhc3MsCiAgICAgICAgICAgICAgICAgY29sb3IgPSBQaHlsdW0pKSArCiAgZmFjZXRfd3JhcCh+IFdFRUsgKyBUUkVBVE1FTlQgKyBHZW5vdHlwZSwKICAgICAgICAgICAgIHNjYWxlcyA9ICJmcmVlX3giLAogICAgICAgICAgICAgbnJvdyA9IDMpICsKICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IikgKwogIHNjYWxlX3hfZGlzY3JldGUoIiIpICsKICBzY2FsZV95X2NvbnRpbnVvdXMoZXhwYW5kID0gYygwLCAwKSkgKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gMCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBoanVzdCA9IDEpKQpnZ3Bsb3RseShwMSkKYGBgCgpgYGB7ciBtZWFuc19jLCBlY2hvID0gRkFMU0UsIHdhcm5pbmcgPSBGQUxTRSwgbWVzc2FnZSA9IEZBTFNFfQpscmEgPC0gcmFfbWVsdChyYSA9IHJhX2MsCiAgICAgICAgICAgICAgIHNhbXBsZXMgPSBzbXBsLAogICAgICAgICAgICAgICBzYW1wbGVfbmFtZSA9ICJTQU1QTEVfTkFNRSIpCgptdSA8LSBkYXRhLnRhYmxlKGFnZ3JlZ2F0ZShscmEkUkEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGJ5ID0gbGlzdChXZWVrID0gbHJhJFdFRUssCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBUcmVhdG1lbnQgPSBscmEkVFJFQVRNRU5ULAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgR2Vub3R5cGUgPSBscmEkR2Vub3R5cGUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBDbGFzcyA9IGxyYSRDbGFzcyksCiAgICAgICAgICAgICAgICAgICAgICAgICAgIEZVTiA9ICJtZWFuIikpCm11WywgdG90YWwgOj0gc3VtKHgpLAogICBieSA9ICJDbGFzcyJdCnVsIDwtIHVuaXF1ZShtdVssIGMoIkNsYXNzIiwgCiAgICAgICAgICAgICAgICAgICAgInRvdGFsIildKQp1bCA8LSB1bFtvcmRlcih0b3RhbCksXQptdSRDbGFzcyA8LSBmYWN0b3IobXUkQ2xhc3MsCiAgICAgICAgICAgICAgICAgICBsZXZlbCA9IHVsJENsYXNzKQptdSR0b3RhbCA8LSBOVUxMCgpkYXRhdGFibGUobXUsCiAgICAgICAgICByb3duYW1lcyA9IEZBTFNFLAogICAgICAgICAgY2FwdGlvbiA9ICJUYXhvbm9taWMgIGNvdW50IHRhYmxlIiwKICAgICAgICAgIGNsYXNzID0gImNlbGwtYm9yZGVyIHN0cmlwZSIsCiAgICAgICAgICBvcHRpb25zID0gbGlzdChzZWFyY2ggPSBGQUxTRSwKICAgICAgICAgICAgICAgICAgICAgICAgIHBhZ2VMZW5ndGggPSAxMCwKICAgICAgICAgICAgICAgICAgICAgICAgIG9yZGVyID0gbGlzdChsaXN0KDMsICdkZXNjJykpKSkgJT4lCiAgZm9ybWF0Q3VycmVuY3koY29sdW1ucyA9IDUsCiAgICAgICAgICAgICAgICAgY3VycmVuY3kgPSAiIiwKICAgICAgICAgICAgICAgICBtYXJrID0gIiwiLAogICAgICAgICAgICAgICAgIGRpZ2l0cyA9IDIpCmBgYAoKCmBgYHtyIG1lYW5zX2NfcDAsIGZpZy53aWR0aCA9IDksIGZpZy5oZWlnaHQgPSA3fQptdSRUcnRfR2Vub3R5cGUgPC0gZmFjdG9yKHBhc3RlKG11JFRyZWF0bWVudCwKICAgICAgICAgICAgICAgICAgICAgICAgICBtdSRHZW5vdHlwZSwKICAgICAgICAgICAgICAgICAgICAgICAgICBzZXAgPSAiXyIpKQoKcDAgPC0gZ2dwbG90KG11LAogICAgICAgICAgICAgYWVzKHggPSBXZWVrLAogICAgICAgICAgICAgICAgIHkgPSB4LAogICAgICAgICAgICAgICAgIGdyb3VwID0gVHJ0X0dlbm90eXBlKSkgKwogIGZhY2V0X3dyYXAofiBDbGFzcywKICAgICAgICAgICAgIHNjYWxlID0gImZyZWVfeSIpICsKICBnZW9tX2xpbmUocG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSgwLjMpKSArCiAgZ2VvbV9wb2ludChhZXMoZmlsbCA9IFRydF9HZW5vdHlwZSksCiAgICAgICAgICAgICBzaGFwZSA9IDIxLAogICAgICAgICAgICAgc2l6ZSA9IDIsCiAgICAgICAgICAgICBhbHBoYSA9IDAuNSwKICAgICAgICAgICAgIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2UoMC4zKSkgKwogIHNjYWxlX3hfZGlzY3JldGUoIiIpICsKICBzY2FsZV95X2NvbnRpbnVvdXMoIlJlbGF0aXZlIEFidW5kYW5jZSAoJSkiKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gInRvcCIsCiAgICAgICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBoanVzdCA9IDEpKQoKdGlmZihmaWxlbmFtZSA9ICJ0bXAvd3RfY2xhc3Nfb3Zlcl90aW1lLnRpZmYiLAogICAgIGhlaWdodCA9IDUsCiAgICAgd2lkdGggPSA3LAogICAgIHVuaXRzID0gImluIiwKICAgICByZXMgPSA2MDAsCiAgICAgY29tcHJlc3Npb24gPSAibHp3K3AiKQpwcmludChwMCkKZ3JhcGhpY3Mub2ZmKCkKCnByaW50KHAwKQpgYGAKCgpgYGB7ciBtZWFuc19jX3AxLCBmaWcuaGVpZ2h0ID0gNSwgZmlnLndpZHRoID0gOX0KcDEgPC0gZ2dwbG90KG11LAogICAgICAgICAgICAgYWVzKHggPSB4LAogICAgICAgICAgICAgICAgIHkgPSBDbGFzcywKICAgICAgICAgICAgICAgICBjb2xvciA9IFRydF9HZW5vdHlwZSwKICAgICAgICAgICAgICAgICBzaGFwZSA9IFdlZWspKSArCiAgZ2VvbV9wb2ludChzaXplID0gMywKICAgICAgICAgICAgIGFscGhhID0gMC41KSArCiAgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gMSwKICAgICAgICAgICAgIGxpbmV0eXBlID0gImRhc2hlZCIpICsKICBzY2FsZV94X2NvbnRpbnVvdXMoIlJlbGF0aXZlIEFidW5kYW5jZSAoJSkiKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gInRvcCIpCgp0aWZmKGZpbGVuYW1lID0gInRtcC93dF9jbGFzc19yYS50aWZmIiwKICAgICBoZWlnaHQgPSA0LAogICAgIHdpZHRoID0gNywKICAgICB1bml0cyA9ICJpbiIsCiAgICAgcmVzID0gNjAwLAogICAgIGNvbXByZXNzaW9uID0gImx6dytwIikKcHJpbnQocDEpCmdyYXBoaWNzLm9mZigpCgpnZ3Bsb3RseShwMSkKYGBgCgojIyAyLiBPcmRlcgpgYGB7ciBjb3VudHNfbywgd2FybmluZz1GQUxTRSxlY2hvPUZBTFNFLG1lc3NhZ2U9RkFMU0UsZmlnLndpZHRoPTE1LGZpZy5oZWlnaHQ9MTV9CmNvdW50c19vIDwtIGNvdW50c19ieV90YXhfcmFuayhkdDEgPSBvdHUxLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYWdncl9ieSA9ICJPcmRlciIpCnJhX28gPC0gcmFfYnlfdGF4X3JhbmsoY291bnRzX28pCgp0YXgucmFua3MgPC0gdW5pcXVlKG90dTFbLCBjKCJQaHlsdW0iLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICJPcmRlciIpXSkKCnJhX28gPC0gbWVyZ2UodGF4LnJhbmtzLAogICAgICAgICAgICAgIHJhX28sCiAgICAgICAgICAgICAgYnkgPSAiT3JkZXIiKQoKdG90YWwgPC0gcm93U3VtcyhyYV9vWywgMzpuY29sKHJhX28pXSkKCnJhX28kT3JkZXIgPC0gZmFjdG9yKHJhX28kT3JkZXIsCiAgICAgICAgICAgICAgICAgICAgIGxldmVscyA9IHJhX28kT3JkZXJbb3JkZXIodG90YWwpXSkKCnJhX28kUGh5bHVtIDwtIGZhY3RvcihyYV9vJFBoeWx1bSwKICAgICAgICAgICAgICAgICAgICAgIGxldmVscyA9IHVuaXF1ZShyYV9vJFBoeWx1bVtvcmRlcih0b3RhbCldKSkKdG1wIDwtIG1lbHQuZGF0YS50YWJsZShkYXRhID0gcmFfbywKICAgICAgICAgICAgICAgICAgICAgICBpZC52YXJzID0gMToyLAogICAgICAgICAgICAgICAgICAgICAgIG1lYXN1cmUudmFycyA9IDM6bmNvbChjb3VudHNfbyksCiAgICAgICAgICAgICAgICAgICAgICAgdmFyaWFibGUubmFtZSA9ICJTQU1QTEVfTkFNRSIsCiAgICAgICAgICAgICAgICAgICAgICAgdmFsdWUubmFtZSA9ICJSQSIpCgp0bXAgPC0gbWVyZ2UoZGF0YS50YWJsZShTQU1QTEVfTkFNRSA9IHNtcGwkU0FNUExFX05BTUUsCiAgICAgICAgICAgICAgICAgICAgICAgIFdFRUsgPSBzbXBsJFdFRUssCiAgICAgICAgICAgICAgICAgICAgICAgIFRSRUFUTUVOVCA9IHNtcGwkVFJFQVRNRU5ULAogICAgICAgICAgICAgICAgICAgICAgICBHZW5vdHlwZSA9IHNtcGwkR2Vub3R5cGUpLAogICAgICAgICAgICAgdG1wLAogICAgICAgICAgICAgYnkgPSAiU0FNUExFX05BTUUiKQoKIyBQbG90IHNhbXBsZXMKcDEgPC0gZ2dwbG90KHRtcCwKICAgICAgICAgICAgIGFlcyh4ID0gU0FNUExFX05BTUUsCiAgICAgICAgICAgICAgICAgeSA9IFJBLAogICAgICAgICAgICAgICAgIGZpbGwgPSBPcmRlciwKICAgICAgICAgICAgICAgICBjb2xvciA9IFBoeWx1bSkpICsKICBmYWNldF93cmFwKH4gV0VFSyArIFRSRUFUTUVOVCArIEdlbm90eXBlLAogICAgICAgICAgICAgc2NhbGVzID0gImZyZWVfeCIsCiAgICAgICAgICAgICBucm93ID0gMykgKwogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiKSArCiAgc2NhbGVfeF9kaXNjcmV0ZSgiIikgKwogIHNjYWxlX3lfY29udGludW91cyhleHBhbmQgPSBjKDAsIDApKSArCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSAwLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhqdXN0ID0gMSkpCmdncGxvdGx5KHAxKQpgYGAKCmBgYHtyIG1lYW5zX28sIGVjaG8gPSBGQUxTRSwgd2FybmluZyA9IEZBTFNFLCBtZXNzYWdlID0gRkFMU0V9CmxyYSA8LSByYV9tZWx0KHJhID0gcmFfbywKICAgICAgICAgICAgICAgc2FtcGxlcyA9IHNtcGwsCiAgICAgICAgICAgICAgIHNhbXBsZV9uYW1lID0gIlNBTVBMRV9OQU1FIikKCm11IDwtIGRhdGEudGFibGUoYWdncmVnYXRlKGxyYSRSQSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgYnkgPSBsaXN0KFdlZWsgPSBscmEkV0VFSywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRyZWF0bWVudCA9IGxyYSRUUkVBVE1FTlQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBHZW5vdHlwZSA9IGxyYSRHZW5vdHlwZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE9yZGVyID0gbHJhJE9yZGVyKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgRlVOID0gIm1lYW4iKSkKbXVbLCB0b3RhbCA6PSBzdW0oeCksCiAgIGJ5ID0gIk9yZGVyIl0KdWwgPC0gdW5pcXVlKG11WywgYygiT3JkZXIiLCAKICAgICAgICAgICAgICAgICAgICAidG90YWwiKV0pCnVsIDwtIHVsW29yZGVyKHRvdGFsKSxdCm11JE9yZGVyIDwtIGZhY3RvcihtdSRPcmRlciwKICAgICAgICAgICAgICAgICAgIGxldmVsID0gdWwkT3JkZXIpCm11JHRvdGFsIDwtIE5VTEwKCmRhdGF0YWJsZShtdSwKICAgICAgICAgIHJvd25hbWVzID0gRkFMU0UsCiAgICAgICAgICBjYXB0aW9uID0gIlRheG9ub21pYyAgY291bnQgdGFibGUiLAogICAgICAgICAgY2xhc3MgPSAiY2VsbC1ib3JkZXIgc3RyaXBlIiwKICAgICAgICAgIG9wdGlvbnMgPSBsaXN0KHNlYXJjaCA9IEZBTFNFLAogICAgICAgICAgICAgICAgICAgICAgICAgcGFnZUxlbmd0aCA9IDEwLAogICAgICAgICAgICAgICAgICAgICAgICAgb3JkZXIgPSBsaXN0KGxpc3QoMywgJ2Rlc2MnKSkpKSAlPiUKICBmb3JtYXRDdXJyZW5jeShjb2x1bW5zID0gNSwKICAgICAgICAgICAgICAgICBjdXJyZW5jeSA9ICIiLAogICAgICAgICAgICAgICAgIG1hcmsgPSAiLCIsCiAgICAgICAgICAgICAgICAgZGlnaXRzID0gMikKYGBgCgpgYGB7ciBtZWFuc19vX3AwLCBmaWcud2lkdGggPSA5LCBmaWcuaGVpZ2h0ID0gN30KbXUkVHJ0X0dlbm90eXBlIDwtIGZhY3RvcihwYXN0ZShtdSRUcmVhdG1lbnQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbXUkR2Vub3R5cGUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VwID0gIl8iKSkKCnAwIDwtIGdncGxvdChtdSwKICAgICAgICAgICAgIGFlcyh4ID0gV2VlaywKICAgICAgICAgICAgICAgICB5ID0geCwKICAgICAgICAgICAgICAgICBncm91cCA9IFRydF9HZW5vdHlwZSkpICsKICBmYWNldF93cmFwKH4gT3JkZXIsCiAgICAgICAgICAgICBzY2FsZSA9ICJmcmVlX3kiKSArCiAgZ2VvbV9saW5lKHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2UoMC4zKSkgKwogIGdlb21fcG9pbnQoYWVzKGZpbGwgPSBUcnRfR2Vub3R5cGUpLAogICAgICAgICAgICAgc2hhcGUgPSAyMSwKICAgICAgICAgICAgIHNpemUgPSAyLAogICAgICAgICAgICAgYWxwaGEgPSAwLjUsCiAgICAgICAgICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKDAuMykpICsKICBzY2FsZV94X2Rpc2NyZXRlKCIiKSArCiAgc2NhbGVfeV9jb250aW51b3VzKCJSZWxhdGl2ZSBBYnVuZGFuY2UgKCUpIikgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJ0b3AiLAogICAgICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaGp1c3QgPSAxKSkKCnRpZmYoZmlsZW5hbWUgPSAidG1wL3d0X09yZGVyX292ZXJfdGltZS50aWZmIiwKICAgICBoZWlnaHQgPSA1LAogICAgIHdpZHRoID0gNywKICAgICB1bml0cyA9ICJpbiIsCiAgICAgcmVzID0gNjAwLAogICAgIGNvbXByZXNzaW9uID0gImx6dytwIikKcHJpbnQocDApCmdyYXBoaWNzLm9mZigpCgpwcmludChwMCkKYGBgCgpgYGB7ciBtZWFuc19vX3AxLCBmaWcuaGVpZ2h0ID0gNSwgZmlnLndpZHRoID0gOX0KcDEgPC0gZ2dwbG90KG11LAogICAgICAgICAgICAgYWVzKHggPSB4LAogICAgICAgICAgICAgICAgIHkgPSBPcmRlciwKICAgICAgICAgICAgICAgICBjb2xvciA9IFRydF9HZW5vdHlwZSwKICAgICAgICAgICAgICAgICBzaGFwZSA9IFdlZWspKSArCiAgZ2VvbV9wb2ludChzaXplID0gMywKICAgICAgICAgICAgIGFscGhhID0gMC41KSArCiAgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gMSwKICAgICAgICAgICAgIGxpbmV0eXBlID0gImRhc2hlZCIpICsKICBzY2FsZV94X2NvbnRpbnVvdXMoIlJlbGF0aXZlIEFidW5kYW5jZSAoJSkiKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gInRvcCIpCgp0aWZmKGZpbGVuYW1lID0gInRtcC93dF9PcmRlcl9yYS50aWZmIiwKICAgICBoZWlnaHQgPSA0LAogICAgIHdpZHRoID0gNywKICAgICB1bml0cyA9ICJpbiIsCiAgICAgcmVzID0gNjAwLAogICAgIGNvbXByZXNzaW9uID0gImx6dytwIikKcHJpbnQocDEpCmdyYXBoaWNzLm9mZigpCgpnZ3Bsb3RseShwMSkKYGBgCgojIyAzLiBGYW1pbHkKYGBge3IgY291bnRzX2YsIHdhcm5pbmc9RkFMU0UsZWNobz1GQUxTRSxtZXNzYWdlPUZBTFNFLGZpZy53aWR0aD0xNSxmaWcuaGVpZ2h0PTE1fQpjb3VudHNfZiA8LSBjb3VudHNfYnlfdGF4X3JhbmsoZHQxID0gb3R1MSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFnZ3JfYnkgPSAiRmFtaWx5IikKcmFfZiA8LSByYV9ieV90YXhfcmFuayhjb3VudHNfZikKCnRheC5yYW5rcyA8LSB1bmlxdWUob3R1MVssIGMoIlBoeWx1bSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkZhbWlseSIpXSkKCnJhX2YgPC0gbWVyZ2UodGF4LnJhbmtzLAogICAgICAgICAgICAgIHJhX2YsCiAgICAgICAgICAgICAgYnkgPSAiRmFtaWx5IikKCnRvdGFsIDwtIHJvd1N1bXMocmFfZlssIDM6bmNvbChyYV9mKV0pCgpyYV9mJEZhbWlseSA8LSBmYWN0b3IocmFfZiRGYW1pbHksCiAgICAgICAgICAgICAgICAgICAgIGxldmVscyA9IHJhX2YkRmFtaWx5W29yZGVyKHRvdGFsKV0pCgpyYV9mJFBoeWx1bSA8LSBmYWN0b3IocmFfZiRQaHlsdW0sCiAgICAgICAgICAgICAgICAgICAgICBsZXZlbHMgPSB1bmlxdWUocmFfZiRQaHlsdW1bb3JkZXIodG90YWwpXSkpCnRtcCA8LSBtZWx0LmRhdGEudGFibGUoZGF0YSA9IHJhX2YsCiAgICAgICAgICAgICAgICAgICAgICAgaWQudmFycyA9IDE6MiwKICAgICAgICAgICAgICAgICAgICAgICBtZWFzdXJlLnZhcnMgPSAzOm5jb2woY291bnRzX2YpLAogICAgICAgICAgICAgICAgICAgICAgIHZhcmlhYmxlLm5hbWUgPSAiU0FNUExFX05BTUUiLAogICAgICAgICAgICAgICAgICAgICAgIHZhbHVlLm5hbWUgPSAiUkEiKQoKdG1wIDwtIG1lcmdlKGRhdGEudGFibGUoU0FNUExFX05BTUUgPSBzbXBsJFNBTVBMRV9OQU1FLAogICAgICAgICAgICAgICAgICAgICAgICBXRUVLID0gc21wbCRXRUVLLAogICAgICAgICAgICAgICAgICAgICAgICBUUkVBVE1FTlQgPSBzbXBsJFRSRUFUTUVOVCwKICAgICAgICAgICAgICAgICAgICAgICAgR2Vub3R5cGUgPSBzbXBsJEdlbm90eXBlKSwKICAgICAgICAgICAgIHRtcCwKICAgICAgICAgICAgIGJ5ID0gIlNBTVBMRV9OQU1FIikKCiMgUGxvdCBzYW1wbGVzCnAxIDwtIGdncGxvdCh0bXAsCiAgICAgICAgICAgICBhZXMoeCA9IFNBTVBMRV9OQU1FLAogICAgICAgICAgICAgICAgIHkgPSBSQSwKICAgICAgICAgICAgICAgICBmaWxsID0gRmFtaWx5LAogICAgICAgICAgICAgICAgIGNvbG9yID0gUGh5bHVtKSkgKwogIGZhY2V0X3dyYXAofiBXRUVLICsgVFJFQVRNRU5UICsgR2Vub3R5cGUsCiAgICAgICAgICAgICBzY2FsZXMgPSAiZnJlZV94IiwKICAgICAgICAgICAgIG5yb3cgPSAzKSArCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIpICsKICBzY2FsZV94X2Rpc2NyZXRlKCIiKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGV4cGFuZCA9IGMoMCwgMCkpICsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDAsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaGp1c3QgPSAxKSkKZ2dwbG90bHkocDEpCmBgYAoKYGBge3IgbWVhbnNfZiwgZWNobyA9IEZBTFNFLCB3YXJuaW5nID0gRkFMU0UsIG1lc3NhZ2UgPSBGQUxTRX0KbHJhIDwtIHJhX21lbHQocmEgPSByYV9mLAogICAgICAgICAgICAgICBzYW1wbGVzID0gc21wbCwKICAgICAgICAgICAgICAgc2FtcGxlX25hbWUgPSAiU0FNUExFX05BTUUiKQoKbXUgPC0gZGF0YS50YWJsZShhZ2dyZWdhdGUobHJhJFJBLAogICAgICAgICAgICAgICAgICAgICAgICAgICBieSA9IGxpc3QoV2VlayA9IGxyYSRXRUVLLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVHJlYXRtZW50ID0gbHJhJFRSRUFUTUVOVCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEdlbm90eXBlID0gbHJhJEdlbm90eXBlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRmFtaWx5ID0gbHJhJEZhbWlseSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgIEZVTiA9ICJtZWFuIikpCm11WywgdG90YWwgOj0gc3VtKHgpLAogICBieSA9ICJGYW1pbHkiXQp1bCA8LSB1bmlxdWUobXVbLCBjKCJGYW1pbHkiLCAKICAgICAgICAgICAgICAgICAgICAidG90YWwiKV0pCnVsIDwtIHVsW29yZGVyKHRvdGFsKSxdCm11JEZhbWlseSA8LSBmYWN0b3IobXUkRmFtaWx5LAogICAgICAgICAgICAgICAgICAgbGV2ZWwgPSB1bCRGYW1pbHkpCm11JHRvdGFsIDwtIE5VTEwKCmRhdGF0YWJsZShtdSwKICAgICAgICAgIHJvd25hbWVzID0gRkFMU0UsCiAgICAgICAgICBjYXB0aW9uID0gIlRheG9ub21pYyAgY291bnQgdGFibGUiLAogICAgICAgICAgY2xhc3MgPSAiY2VsbC1ib3JkZXIgc3RyaXBlIiwKICAgICAgICAgIG9wdGlvbnMgPSBsaXN0KHNlYXJjaCA9IEZBTFNFLAogICAgICAgICAgICAgICAgICAgICAgICAgcGFnZUxlbmd0aCA9IDEwLAogICAgICAgICAgICAgICAgICAgICAgICAgRmFtaWx5ID0gbGlzdChsaXN0KDMsICdkZXNjJykpKSkgJT4lCiAgZm9ybWF0Q3VycmVuY3koY29sdW1ucyA9IDUsCiAgICAgICAgICAgICAgICAgY3VycmVuY3kgPSAiIiwKICAgICAgICAgICAgICAgICBtYXJrID0gIiwiLAogICAgICAgICAgICAgICAgIGRpZ2l0cyA9IDIpCmBgYAoKTk9URTogb25seSB0aGUgZmlyc3QgMjQgZmFtaWxpZXMgaGFkIGxhcmdlIGVub3VnaCBjb3VudHMgLSBwbG90aW5nIG9ubHkgdGhlbS4gIAogIApgYGB7ciBtZWFuc19mX3AwLCBmaWcud2lkdGggPSA5LCBmaWcuaGVpZ2h0ID0gN30KbXUkVHJ0X0dlbm90eXBlIDwtIGZhY3RvcihwYXN0ZShtdSRUcmVhdG1lbnQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbXUkR2Vub3R5cGUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VwID0gIl8iKSkKbXUgPC0gZHJvcGxldmVscyhtdVtGYW1pbHkgPT0gbGV2ZWxzKG11JEZhbWlseSlbMToyNF0sIF0pCgpwMCA8LSBnZ3Bsb3QobXUsCiAgICAgICAgICAgICBhZXMoeCA9IFdlZWssCiAgICAgICAgICAgICAgICAgeSA9IHgsCiAgICAgICAgICAgICAgICAgZ3JvdXAgPSBUcnRfR2Vub3R5cGUpKSArCiAgZmFjZXRfd3JhcCh+IEZhbWlseSwKICAgICAgICAgICAgIHNjYWxlID0gImZyZWVfeSIpICsKICBnZW9tX2xpbmUocG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSgwLjMpKSArCiAgZ2VvbV9wb2ludChhZXMoZmlsbCA9IFRydF9HZW5vdHlwZSksCiAgICAgICAgICAgICBzaGFwZSA9IDIxLAogICAgICAgICAgICAgc2l6ZSA9IDIsCiAgICAgICAgICAgICBhbHBoYSA9IDAuNSwKICAgICAgICAgICAgIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2UoMC4zKSkgKwogIHNjYWxlX3hfZGlzY3JldGUoIiIpICsKICBzY2FsZV95X2NvbnRpbnVvdXMoIlJlbGF0aXZlIEFidW5kYW5jZSAoJSkiKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gInRvcCIsCiAgICAgICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBoanVzdCA9IDEpKQoKdGlmZihmaWxlbmFtZSA9ICJ0bXAvd3RfRmFtaWx5X292ZXJfdGltZS50aWZmIiwKICAgICBoZWlnaHQgPSA1LAogICAgIHdpZHRoID0gNywKICAgICB1bml0cyA9ICJpbiIsCiAgICAgcmVzID0gNjAwLAogICAgIGNvbXByZXNzaW9uID0gImx6dytwIikKcHJpbnQocDApCmdyYXBoaWNzLm9mZigpCgpwcmludChwMCkKYGBgCgojIFNlc3Npb24gSW5mb3JtYXRpb24KYGBge3IgaW5mbyxldmFsPVRSVUV9CnNlc3Npb25JbmZvKCkKYGBg